﻿
Imports osi.root.constants
Imports osi.root.template
Imports osi.root.connector
Imports lock_t = osi.root.lock.slimlock.monitorlock

Public MustInherit Class pool(Of T, _THREADSAFE As _boolean, _RNDSELECT As _boolean, _ENABLEAPPEND As _boolean)
    Public Const invalid_index As Int64 = npos
    Private Shared _tf As Boolean = False
    Private Shared _rnd As Boolean = False
    Private Shared _ea As Boolean = False
    Private _lock As lock_t

    Shared Sub New()
        _tf = +(alloc(Of _THREADSAFE)())
        _rnd = +(alloc(Of _RNDSELECT)())
        _ea = +(alloc(Of _ENABLEAPPEND)())
    End Sub

    Protected Overridable Function create() As T
        Return alloc(Of T)()
    End Function

    Private Shared Function randomselect() As Boolean
        Return _rnd
    End Function

    Private Shared Function threadsafe() As Boolean
        Return _tf
    End Function

    Private Shared Function enable_append() As Boolean
        Return _ea
    End Function

#If Not PocketPC AndAlso Not Smartphone Then
    <ThreadStatic()> Private Shared index As Int64? = Nothing

    Public Function current_instance() As T
        Return at(index)
    End Function

    Public Function current_index() As Int64
        k_assert(index.Value() <> invalid_index, "has not set index in current thread.")
        Return index
    End Function

    Public Function [get](ByRef inst As T) As Boolean
        If Not index.HasValue() Then
            index = invalid_index
        End If
        k_assert(index.Value() = invalid_index, "index is already set to ", index)
        Return [get](index, inst)
    End Function

    Public Function release() As Boolean
        If release(current_index()) Then
            index = invalid_index
            Return True
        Else
            Return False
        End If
    End Function
#End If

    Protected MustOverride Property at(ByVal index As Int64) As T
    Protected MustOverride Property free(ByVal index As Int64) As Boolean
    Protected MustOverride Function size() As Int64

    Protected Overridable Function append() As Int64
        Return invalid_index
    End Function

    Private Sub lock()
        If threadsafe() Then
            _lock.wait()
        End If
    End Sub

    Private Sub unlock()
        If threadsafe() Then
            _lock.release()
        End If
    End Sub

    Public Function [get](ByRef i As Int64, ByRef inst As T) As Boolean
        lock()
        If randomselect() Then
            Dim start As Int64
            start = rnd(0, size(), True)
            i = start
            Do
                If free(i) Then
                    Exit Do
                End If
                i += 1
                If i = size() Then
                    i = 0
                End If
            Loop Until i = start
            If i = start Then
                i = size()
            End If
        Else
            For i = 0 To size() - 1
                If free(i) Then
                    Exit For
                End If
            Next
        End If

        If Not valid_index(i) AndAlso enable_append() Then
            i = append()
        End If

        Dim rtn As Boolean = False
        If valid_index(i) Then
            If at(i) Is Nothing Then
                at(i) = create()
            End If
            inst = at(i)
            free(i) = False
            rtn = True
        Else
            rtn = False
        End If

        unlock()
        Return rtn
    End Function

    Public Function valid_index(ByVal index As Int64) As Boolean
        Return index < size() AndAlso index >= 0
    End Function

    Public Function release(ByVal i As Int64) As Boolean
        If valid_index(i) Then
            free(i) = True
            Return True
        Else
            Return False
        End If
    End Function
End Class
